<?php

namespace app\admin\controller;

use app\common\controller\Backend;
use fast\Random;
use think\Cache;
use think\Config;
use think\Db;
use think\Lang;
//use think\log;

/**
 * Ajax异步请求接口
 * @internal
 */
class Ajax extends Backend
{

    protected $noNeedLogin = ['lang'];
    protected $noNeedRight = ['*'];
    protected $layout = '';

    public function _initialize()
    {
        parent::_initialize();

        //设置过滤方法
        $this->request->filter(['strip_tags', 'htmlspecialchars']);
    }

    /**
     * 加载语言包
     */
    public function lang()
    {
        header('Content-Type: application/javascript');
        $controllername = input("controllername");
        //默认只加载了控制器对应的语言名，你还根据控制器名来加载额外的语言包
        $this->loadlang($controllername);
        return jsonp(Lang::get(), 200, [], ['json_encode_param' => JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE]);
    }

    /**
     * 上传文件
     */
    public function upload()
    {
        Config::set('default_return_type', 'json');
        $file = $this->request->file('file');
        if (empty($file))
        {
            $this->error(__('No file upload or server upload limit exceeded'));
        }

        
        //判断是否已经存在附件
        $sha1 = $file->hash();

        $upload = Config::get('upload');

        preg_match('/(\d+)(\w+)/', $upload['maxsize'], $matches);
        $type = strtolower($matches[2]);
        $typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3];
        $size = (int) $upload['maxsize'] * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0);
        $fileInfo = $file->getInfo();
        $suffix = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION));
        $suffix = $suffix ? $suffix : 'file';

        $mimetypeArr = explode(',', $upload['mimetype']);
        $typeArr = explode('/', $fileInfo['type']);
        //验证文件后缀
        if ($upload['mimetype'] !== '*' && !in_array($suffix, $mimetypeArr) && !in_array($fileInfo['type'], $mimetypeArr) && !in_array($typeArr[0] . '/*', $mimetypeArr))
        {
            $this->error(__('Uploaded file format is limited'));
        }
        $replaceArr = [
            '{year}'     => date("Y"),
            '{mon}'      => date("m"),
            '{day}'      => date("d"),
            '{hour}'     => date("H"),
            '{min}'      => date("i"),
            '{sec}'      => date("s"),
            '{random}'   => Random::alnum(16),
            '{random32}' => Random::alnum(32),
            '{filename}' => $suffix ? substr($fileInfo['name'], 0, strripos($fileInfo['name'], '.')) : $fileInfo['name'],
            '{suffix}'   => $suffix,
            '{.suffix}'  => $suffix ? '.' . $suffix : '',
            '{filemd5}'  => md5_file($fileInfo['tmp_name']),
        ];
        $savekey = $upload['savekey'];
        $savekey = str_replace(array_keys($replaceArr), array_values($replaceArr), $savekey);

        $uploadDir = substr($savekey, 0, strripos($savekey, '/') + 1);
        $fileName = substr($savekey, strripos($savekey, '/') + 1);
        //
        $splInfo = $file->validate(['size' => $size])->move(ROOT_PATH . '/public' . $uploadDir, $fileName);
        if ($splInfo)
        {
            $imagewidth = $imageheight = 0;
            if (in_array($suffix, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'swf']))
            {
                $imgInfo = getimagesize($splInfo->getPathname());
                $imagewidth = isset($imgInfo[0]) ? $imgInfo[0] : $imagewidth;
                $imageheight = isset($imgInfo[1]) ? $imgInfo[1] : $imageheight;
            }
            $params = array(
                'filesize'    => $fileInfo['size'],
                'imagewidth'  => $imagewidth,
                'imageheight' => $imageheight,
                'imagetype'   => $suffix,
                'imageframes' => 0,
                'mimetype'    => $fileInfo['type'],
                'url'         => $uploadDir . $splInfo->getSaveName(),
                'uploadtime'  => time(),
                'storage'     => 'local',
                'sha1'        => $sha1,
            );
            $attachment = model("attachment");
            $attachment->data(array_filter($params));
            $attachment->save();
            \think\Hook::listen("upload_after", $attachment);
            $this->success(__('Upload successful'), null, [
                'url' => $uploadDir . $splInfo->getSaveName()
            ]);
        }
        else
        {
            // 上传失败获取错误信息
            $this->error($file->getError());
        }
    }

    /**
     * 通用排序
     */
    public function weigh()
    {
        //排序的数组
        $ids = $this->request->post("ids");
        //拖动的记录ID
        $changeid = $this->request->post("changeid");
        //操作字段
        $field = $this->request->post("field");
        //操作的数据表
        $table = $this->request->post("table");
        //排序的方式
        $orderway = $this->request->post("orderway", 'strtolower');
        $orderway = $orderway == 'asc' ? 'ASC' : 'DESC';
        $sour = $weighdata = [];
        $ids = explode(',', $ids);
        $prikey = 'id';
        $pid = $this->request->post("pid");
        //限制更新的字段
        $field = in_array($field, ['weigh']) ? $field : 'weigh';

        // 如果设定了pid的值,此时只匹配满足条件的ID,其它忽略
        if ($pid !== '')
        {
            $hasids = [];
            $list = Db::name($table)->where($prikey, 'in', $ids)->where('pid', 'in', $pid)->field('id,pid')->select();
            foreach ($list as $k => $v)
            {
                $hasids[] = $v['id'];
            }
            $ids = array_values(array_intersect($ids, $hasids));
        }

        //直接修复排序
        $one = Db::name($table)->field("{$field},COUNT(*) AS nums")->group($field)->having('nums > 1')->find();
        if ($one)
        {
            $list = Db::name($table)->field("$prikey,$field")->order($field, $orderway)->select();
            foreach ($list as $k => $v)
            {
                Db::name($table)->where($prikey, $v[$prikey])->update([$field => $k + 1]);
            }
            $this->success();
        }
        else
        {
            $list = Db::name($table)->field("$prikey,$field")->where($prikey, 'in', $ids)->order($field, $orderway)->select();
            foreach ($list as $k => $v)
            {
                $sour[] = $v[$prikey];
                $weighdata[$v[$prikey]] = $v[$field];
            }
            $position = array_search($changeid, $ids);
            $desc_id = $sour[$position];    //移动到目标的ID值,取出所处改变前位置的值
            $sour_id = $changeid;
            $desc_value = $weighdata[$desc_id];
            $sour_value = $weighdata[$sour_id];
            //echo "移动的ID:{$sour_id}\n";
            //echo "替换的ID:{$desc_id}\n";
            $weighids = array();
            $temp = array_values(array_diff_assoc($ids, $sour));
            foreach ($temp as $m => $n)
            {
                if ($n == $sour_id)
                {
                    $offset = $desc_id;
                }
                else
                {
                    if ($sour_id == $temp[0])
                    {
                        $offset = isset($temp[$m + 1]) ? $temp[$m + 1] : $sour_id;
                    }
                    else
                    {
                        $offset = isset($temp[$m - 1]) ? $temp[$m - 1] : $sour_id;
                    }
                }
                $weighids[$n] = $weighdata[$offset];
                Db::name($table)->where($prikey, $n)->update([$field => $weighdata[$offset]]);
            }
            $this->success();
        }
    }

    /**
     * 清空系统缓存
     */
    public function wipecache()
    {
        $wipe_cache_type = ['TEMP_PATH', 'LOG_PATH', 'CACHE_PATH'];
        foreach ($wipe_cache_type as $item)
        {
            $dir = constant($item);
            if (!is_dir($dir))
                continue;
            rmdirs($dir);
        }
        Cache::clear();
        \think\Hook::listen("wipecache_after");
        $this->success();
    }

    /**
     * 读取分类数据,联动列表
     */
    public function category()
    {
        $type = $this->request->get('type');
        $pid = $this->request->get('pid');
        $where = ['status' => 'normal'];
        $categorylist = null;
        if ($pid !== '')
        {
            if ($type)
            {
                $where['type'] = $type;
            }
            if ($pid)
            {
                $where['pid'] = $pid;
            }

            $categorylist = Db::name('category')->where($where)->field('id as value,name')->order('weigh desc,id desc')->select();
        }
        $this->success('', null, $categorylist);
    }

    /**
     * 读取省市区数据,联动列表
     */
    public function area()
    {
        $province = $this->request->get('province');
        $city = $this->request->get('city');
        $where = ['pid' => 0, 'level' => 1];
        $provincelist = null;
        if ($province !== '')
        {
            if ($province)
            {
                $where['pid'] = $province;
                $where['level'] = 2;
            }
            if ($city !== '')
            {
                if ($city)
                {
                    $where['pid'] = $city;
                    $where['level'] = 3;
                }
                $provincelist = Db::name('area')->where($where)->field('id as value,name')->select();
            }
        }
        $this->success('', null, $provincelist);
    }

    // 读取仪器类型数据，联动列表
    public function instype()
    {
        $instumentname = $this->request->get('iname');
        $typelist = [];
        if(!empty($instumentname)) {
            $where = ['title' => $instumentname];
            $typelist = Db::name('instrument')->where($where)->field('id, type as name')->select();
        }    
        exit(json_encode($typelist));
    }


     /**
     * 上传仪器数据文件
     */
    public function uploadfiledata()
    {
        Config::set('default_return_type', 'json');
        $file = $this->request->file('file');

        $_instype = $this->request->post('instype');
        $_filedataId = $this->request->post('filedataId');

        //$_filename = $this->request->post('name');
        if (empty($file))
        {
            $this->error(__('No file upload or server upload limit exceeded'));
        }

        if(empty($_instype) || empty($_filedataId)) {
            $this->error(__('Unknow the type of the instrument\'s file.'));
        }

        // 获得仪器类型设置信息
        $r1 = Db::name('instrument')->where(['type' => $_instype])->field('maxfilenum, storagespace')->find();
       // $r1 = model('Instrument')->getInstrumentInfo(['type' => 'ZD18'],'maxfilenum, storagespace');
        //Log::record('[UploadFileData] $r1 => '.var_export($r1, true),'info');


        // 获得该用户已经上传文件的数量和容量--- 从文件附件表中取数据
        // $w = [
        //     'admin_id' => $this->auth->id,
        //     'state' => array('in', ['0','1']), 
        //     'instrumenttype' => $_instype,
        // ];
        // $r = Db::name('fileattachment')->where($w)->field('count(id) as num, sum(filesize) as size ')->find();

        // 获得该用户已经上传文件的数量和容量--- 从文件数据表中
        $w = [
            'admin_id' => $this->auth->id,
            'state' => '1', 
            'instumenttype' => $_instype,
        ];
        $r = Db::name('filedata')->where($w)->field('count(filenum) as num, sum(filecapacity) as size ')->find();
        //Log::record('[UploadFileData] $r => '.var_export($r, true),'info');


        $fileInfo = $file->getInfo();

        // 大小限制
        $_maxSpace = $r1['storagespace'] * 1024 * 1024;
        if( ($r['size'] + $fileInfo['size']) > $_maxSpace ) {
            $_remainSpace = $_remainSpaceB = $_maxSpace - $r['size'];
            $_remainSpace = format_bytes($_remainSpace);
            $this->error(__('Exceed the maximum space limit.The remaining space is:').$_remainSpace.' ('.$_remainSpaceB.' B) .');
        }

        // 最大文件数
        if( $r['num']  >= $r1['maxfilenum'] ) {
            $this->error(__('Exceed the maximum file number limit.The remaining number is:').($r1['maxfilenum'] - $r['num']).'.');
        }

        //$instype = $this->request->
        // echo '<pre>';
        // print_r($this->request->post());exit;
  
        //判断是否已经存在附件
        $sha1 = $file->hash();

        $upload = Config::get('UploadFileData');
        // Log::record('[UploadFileData] upload => '.var_export($upload, true),'info');

        // 根据仪器类型获得仪器数据的后缀格式
        $instrumenttype = $this->getInstrumentSuffix($_instype);
        if(!empty($instrumenttype)) {
            $upload['mimetype'] = $instrumenttype;
        } 
        // Log::record('[UploadFileData] upload2 => '.var_export($upload, true),'info');

        preg_match('/(\d+)(\w+)/', $upload['maxsize'], $matches);
        $type = strtolower($matches[2]);
        $typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3];
        $size = (int) $upload['maxsize'] * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0);
        

         // Log::record('[UploadFileData]'.var_export($fileInfo, true),'info');

        $suffix = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION));
        $suffix = $suffix ? $suffix : 'file';

        // Log::record('[UploadFileData] suffix='.$suffix,'info');

        $mimetypeArr = explode(',', $upload['mimetype']);
        $typeArr = explode('/', $fileInfo['type']);
        //验证文件后缀
        if ($upload['mimetype'] !== '*' && !in_array($suffix, $mimetypeArr) && !in_array($fileInfo['type'], $mimetypeArr) && !in_array($typeArr[0] . '/*', $mimetypeArr))
        {
            $this->error(__('Uploaded file format is limited'));
        }
        $replaceArr = [
            '{year}'     => date("Y"),
            '{mon}'      => date("m"),
            '{day}'      => date("d"),
            '{hour}'     => date("H"),
            '{min}'      => date("i"),
            '{sec}'      => date("s"),
            '{random}'   => Random::alnum(16),
            '{random32}' => Random::alnum(32),
            '{filename}' => $suffix ? substr($fileInfo['name'], 0, strripos($fileInfo['name'], '.')) : $fileInfo['name'],
            '{suffix}'   => $suffix,
            '{.suffix}'  => $suffix ? '.' . $suffix : '',
            '{filemd5}'  => md5_file($fileInfo['tmp_name']),
        ];
        $savekey = $upload['savekey'];
        $savekey = str_replace(array_keys($replaceArr), array_values($replaceArr), $savekey);

        $uploadDir = substr($savekey, 0, strripos($savekey, '/') + 1);
        $fileName = substr($savekey, strripos($savekey, '/') + 1);
        //
        $splInfo = $file->validate(['size' => $size])->move(ROOT_PATH . '/public' . $uploadDir, $fileName);

         // Log::record('[UploadFileData] splInfo='.var_export($splInfo, true),'info');

        if ($splInfo)
        {
            $imagewidth = $imageheight = 0;
            if (in_array($suffix, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'swf']))
            {
                $imgInfo = getimagesize($splInfo->getPathname());
                $imagewidth = isset($imgInfo[0]) ? $imgInfo[0] : $imagewidth;
                $imageheight = isset($imgInfo[1]) ? $imgInfo[1] : $imageheight;
            }
            $params = array(
                'admin_id'    => $this->auth->id,
                'originalname'    => $fileInfo['name'],
                'instrumenttype'    => $_instype,
                'filesize'    => $fileInfo['size'],
                'instrumentsuffix'  => $instrumenttype,
                'mimetype'    => $fileInfo['type'],
                'url'         => $uploadDir . $splInfo->getSaveName(),
                'uploadtime'  => time(),
                'storage'     => 'local',
                'sha1'        => $sha1,
            );
            $attachment = model("fileattachment");
            $attachment->data(array_filter($params));
            $attachment->save();

            \think\Hook::listen("upload_after", $attachment);
            $this->success(__('Upload successful'), null, [
                //'url' => $uploadDir . $splInfo->getSaveName(),
                'url' => $fileInfo['name'],
                'fileId' => $attachment->id,
                'fileSize' => $fileInfo['size'],
                'filedataId' => $_filedataId,
            ]);
        }
        else
        {
            // 上传失败获取错误信息
            $this->error($file->getError());
        }
    }


    // 根据登陆ID和仪器类型获得该用户上传数据文件的一些信息
    /*
     * 根据仪器类型获得
     * (1) 该仪器支持的数据文件类型
     * (2) 该仪器设置的最大允许上传文件的数量，容量
     * (3) 该用户仪器已经上传的文件数及容量
    */
    public function stypeinfo() 
    {
        $type = $this->request->get('instype');      
        $r = [
            'suffix' => [],
            'setting' => ['maxNum' => 0, 'maxSize' => 0],
            'used' => ['num' => 0, 'size' => 0],
            'remain' => ['num' => 0, 'size' => 0, 'formatSize' => 0]
        ];
       
        if(empty($type)) 
        {
            exit(json_encode($r));
        }

        // 
        $where = ['type' => $type];
        $data =  Db::name('instrument')->where($where)->field('suffix1, suffix2, suffix3, maxfilenum as maxNum, storagespace as maxSize')->find();

        if(empty($data)) 
        {
            exit(json_encode($r));
        }

        $data = array_map('strtolower', $data);
        $data = array_unique($data);
        $data = array_diff($data, ['-']);

        // 后缀
        for($i = 1; $i <= 3; $i++) 
        {
            $name = 'suffix'.$i;
            if(isset($data[$name]) && !empty($data[$name])) 
            {
                array_push($r['suffix'], $data[$name]);
            }  
        }
        if($r['suffix']) {
            $r['suffix'] = implode(",", $r['suffix']);
        };
        // 设置
        $r['setting']['maxNum'] = $data['maxNum'];
        $r['setting']['maxSize'] = $data['maxSize'] * 1024 * 1024;

        $where = [
            'admin_id' => $this->auth->id,
            'instumenttype' => $type,
            'state' => '1',
        ];        
        $row = Db::name('filedata')->where($where)->field('sum(filenum) as num, sum(filecapacity) as size ')->find();

        $r['used']['num'] = !empty($row['num']) ? $row['num'] : 0;
        $r['used']['size'] = !empty($row['size']) ? $row['size'] : 0;

        $r['remain']['num'] =  $r['setting']['maxNum'] - $r['used']['num'];
        $r['remain']['size'] =  $r['setting']['maxSize'] - $r['used']['size'];
        $r['remain']['formatSize'] =   ($r['remain']['size']) < 0 ? '0 B' :  format_bytes($r['remain']['size']);

        exit(json_encode($r));
    }

    // 根据仪器类型获得该仪器支持的数据文件后缀类型
    // 仪器类型唯一
    public function getInstrumentSuffix($type = '') {
        if(empty($type)) {
            return null;
        }

        $where = ['type' => $type];
        $data =  Db::name('instrument')->where($where)->field('suffix1, suffix2, suffix3')->find();        

        $r = []; 
        if($data) {                       
            $r= array_map('strtolower', $data);                
            $r = array_unique($r);
            $r = array_diff($r, ['-']);            
        }

        if($r) {
            return implode(",", $r);
        } else {
            return null;
        };

    }

}
